const mapNode = document.querySelector('.map') // 地图
const scoreNode = document.querySelector('.score') // 分数
const speedNode = document.querySelector('.speed') // 速度
const pauseNode = document.querySelector('.pause') // 暂停

let snakeInterval = null // 蛇的运动定时器
let updateHeaderInterval = null // 更新头部信息定时器

let snakeSpeed = 500 // 蛇的速度

// 生成20 * 20 的小格子放在map中 map的大小为600 * 400
const createGrid = () => {
  for (let i = 0; i < 600; i++) {
    const node = document.createElement('div')
    node.classList.add('grid')
    mapNode.appendChild(node)
  }
}
createGrid()

// 初始化速度
const initSpeed = () => {
  speedNode.innerHTML = `速度：${snakeSpeed}`
}
initSpeed()

// 食物类
class Food {
  constructor() {
    this.node = document.createElement('div')
    this.node.classList.add('food')
    mapNode.appendChild(this.node)
    // 随机生成一个背景色
    this.node.style.backgroundColor = `#${Math.floor(
      Math.random() * 16777215
    ).toString(16)}`
    this.x = 0
    this.y = 0
    this.create()
  }
  // 随机生成一个位置
  create() {
    this.x = Math.floor(Math.random() * 30) * 20
    this.y = Math.floor(Math.random() * 20) * 20
    this.node.style.left = `${this.x}px`
    this.node.style.top = `${this.y}px`
  }
  // 销毁食物
  destory() {
    this.node.remove()
  }
}
// 创建食物实例
const food = new Food()

// 蛇类
class Snake {
  constructor() {
    this.direction = 'right'
    this.speed = 200
    this.body = []
    this.generate()
  }
  // 创建蛇
  create() {
    const header = this.body[0] || false
    const pos = { x: 0, y: 0 }
    const node = document.createElement('div')
    node.classList.add('snake')
    node.classList.add('snake_body')
    switch (this.direction) {
      case 'right':
        pos.x = header ? header.x + 20 : 0
        pos.y = header ? header.y : 0
        node.x = pos.x
        node.y = pos.y
        node.style.left = `${pos.x}px`
        node.style.top = `${pos.y}px`
        this.body.unshift(node)
        mapNode.appendChild(node)
        break
      case 'left':
        pos.x = header ? header.x - 20 : 0
        pos.y = header ? header.y : 0
        node.x = pos.x
        node.y = pos.y
        node.style.left = `${pos.x}px`
        node.style.top = `${pos.y}px`
        this.body.unshift(node)
        mapNode.appendChild(node)
        break
      case 'up':
        pos.x = header ? header.x : 0
        pos.y = header ? header.y - 20 : 0
        node.x = pos.x
        node.y = pos.y
        node.style.left = `${pos.x}px`
        node.style.top = `${pos.y}px`
        this.body.unshift(node)
        mapNode.appendChild(node)
        break
      case 'down':
        pos.x = header ? header.x : 0
        pos.y = header ? header.y + 20 : 0
        node.x = pos.x
        node.y = pos.y
        node.style.left = `${pos.x}px`
        node.style.top = `${pos.y}px`
        this.body.unshift(node)
        mapNode.appendChild(node)
        break
    }
  }
  // 生成一条蛇
  generate() {
    for (let i = 0; i < 4; i++) {
      this.create()
    }
    this.body[0].className = 'snake snake_header'
  }
  // 移动
  move() {
    const a = this.body.pop()
    a.remove()
    this.create()
    const snake = document.getElementsByClassName('snake')
    for (let i = 0; i < snake.length; i++) {
      snake[i].classList = 'snake_body snake'
    }
    snake[snake.length - 1].className = 'snake_header snake'
  }
  // 跟新蛇头
  updateHeader() {
    const snake = document.getElementsByClassName('snake')
    for (let i = 0; i < snake.length; i++) {
      snake[i].classList.remove('head')
    }
    snake[snake.length - 1].classList.add('head')
  }
  // 改变方向
  changeDirection(direction) {
    if (this.direction === direction) return
    // 不能掉头
    if (this.direction === 'left' && direction === 'right') return
    if (this.direction === 'right' && direction === 'left') return
    if (this.direction === 'up' && direction === 'down') return
    if (this.direction === 'down' && direction === 'up') return
    this.direction = direction
  }
}
const snake = new Snake()
// 跟新蛇头
updateHeaderInterval = setInterval(() => {
  snake.updateHeader()
}, 50)

// 控制速度的增加
const editSpeed = (s) => {
  if (s > 20) {
    snakeSpeed = 100
  } else if (s > 15) {
    snakeSpeed = 200
  } else if (s > 10) {
    snakeSpeed = 300
  } else if (s > 5) {
    snakeSpeed = 400
  } else {
    snakeSpeed = 500
  }
  initSpeed()
  clearInterval(snakeInterval)
  // 重新开始定时器
  snakeInterval = setInterval(() => {
    snake.move()
    // 吃到食物
    eatFood()
    // 碰到墙壁
    hitWall()
    // 蛇头吃到身子游戏失败
    hitBody()
  }, snakeSpeed)
}

// 蛇吃到食物
function eatFood() {
  if (snake.body[0].x === food.x && snake.body[0].y === food.y) {
    snake.create()
    food.create()
    const s = Number(scoreNode.innerHTML.split(':')[1]) + 1
    scoreNode.innerHTML = `得分: ${s}`
    editSpeed(s)
  }
}

// 游戏重新开始
function restart() {
  snake.direction = 'right'
  clearInterval(snakeInterval)
  snake.body.forEach((item) => {
    item.remove()
  })
  snake.body = []
  snake.generate()
  food.create()
  scoreNode.innerHTML = '得分: 0'
  speedNode.innerHTML = '速度: 500'
  editSpeed(0)
  continueGame()
}

// 蛇碰到墙壁
function hitWall() {
  if (
    snake.body[0].x < 0 ||
    snake.body[0].x > 600 ||
    snake.body[0].y < 0 ||
    snake.body[0].y > 400
  ) {
    alert('游戏结束')

    clearInterval(snakeInterval)
    restart()
  }
}

// 游戏暂停
function pause() {
  clearInterval(snakeInterval)
}
// 游戏继续
function continueGame() {
  if (snakeInterval) clearInterval(snakeInterval)
  snakeInterval = setInterval(() => {
    snake.move()
    // 吃到食物
    eatFood()
    // 碰到墙壁
    hitWall()
    // 蛇头吃到身子游戏失败
    hitBody()
  }, snakeSpeed)
}

const pauseAndStart = () => {
  if (pauseNode.innerHTML === '暂停') {
    pause()
    pauseNode.innerHTML = '继续'
  } else {
    continueGame()
    pauseNode.innerHTML = '暂停'
  }
}

// 点击游戏暂停或者继续
pauseNode.addEventListener('click', pauseAndStart)

// 按下空格游戏暂停或者继续
window.addEventListener('keydown', (e) => {
  if (e.code === 'Space') {
    pauseAndStart()
  }
})

// 蛇头吃到身子游戏失败
function hitBody() {
  const head = snake.body.find((item, index) => {
    return item.className.includes('head')
  })
  const body = snake.body.filter((item, index) => {
    return item.className.includes('head') === false
  })
  if (body.some((item) => item.x === head.x && item.y === head.y)) {
    alert('游戏结束')
    clearInterval(snakeInterval)
    restart()
  }
}

// 控制蛇的运动
snakeInterval = setInterval(() => {
  snake.move()
  // 吃到食物
  eatFood()
  // 碰到墙壁
  hitWall()
  // 蛇头吃到身子游戏失败
  hitBody()
}, snakeSpeed)

// 游戏结束
function gameOver() {
  clearInterval(snakeInterval)
}

// 改变蛇运动的方向
document.addEventListener('keydown', (e) => {
  switch (e.key) {
    case 'ArrowLeft':
      snake.changeDirection('left')
      break
    case 'ArrowUp':
      snake.changeDirection('up')
      break
    case 'ArrowRight':
      snake.changeDirection('right')
      break
    case 'ArrowDown':
      snake.changeDirection('down')
      break
  }
})
